#include "modules/record_mgr.h"
	
RecordInfo* RecordInfo::ptr = NULL;

void RecordManager::add_record(string &tablename, Record rec)
{
	BYTE block[BLOCK_SIZE] = {0};
	//Get the empty slot
	RecordId id = ri.get_empty_record(tablename);
	UINT32 rec_size = ri.get_record_size(tablename);
	//If it is not a new block read the block
	if(id.slot_num != 0)
	{
		bm.read_block(tablename, id.block_num, block);
	}
	memcpy(&block[id.slot_num * rec_size],  rec.get_data(), rec_size);
	bm.write_block(tablename, id.block_num, block);
}

vector<Record> RecordManager::read_records(string &tablename)
{
	vector<Record> result;
	BYTE block[BLOCK_SIZE] = {0};
	UINT32 num_blocks = ri.get_num_blocks(tablename);
	UINT32 num_recs = ri.get_max_num_records(tablename);
	UINT32 rec_size = ri.get_record_size(tablename);
	
	for(UINT32 i=0; i<num_blocks; i++)
	{
		if(i == num_blocks - 1)
		{
			num_recs = ri.get_num_records(tablename, i);
		}
		bm.read_block(tablename, i, block);		
		for(UINT32 j=0; j<num_recs; j++)
		{
			Record r(rec_size / 4);
			RecordId id = {i,j};
			r.id = id;
			r.set_data(&block[j*rec_size]);
			result.push_back(r);
		}
	}
	return result;
}

vector<Record> RecordManager::read_records(string &tablename, Condition cond)
{
	vector<Record> result;
	BYTE block[BLOCK_SIZE] = {0};
	UINT32 num_blocks = ri.get_num_blocks(tablename);
	UINT32 num_recs = ri.get_max_num_records(tablename);
	UINT32 rec_size = ri.get_record_size(tablename);
	for(UINT32 i=0; i<num_blocks; i++)
	{
		if(i == num_blocks - 1)
		{
			num_recs = ri.get_num_records(tablename, i);
		}
		bm.read_block(tablename, i, block);		
		for(UINT32 j=0; j<num_recs; j++)
		{
			Record r(rec_size / 4);
			RecordId id = {i,j};
			r.id = id;
			r.set_data(&block[j*rec_size]);
			if(r.check(cond))
			{
				result.push_back(r);
			}
		}
	}
	return result;
}

class RecordCompare
{
public:
	bool operator() (const Record &r1, const Record &r2)
	{
		return (r1.id.block_num < r2.id.block_num) || (r1.id.slot_num < r2.id.slot_num);
	}
};

vector<Record> RecordManager::merge_records(vector<Record> vec1, vector<Record> vec2)
{
	vector<Record> result(vec1.size() + vec2.size());
	RecordCompare comp;
	vector<Record>::iterator iter =set_union(vec1.begin(), vec1.end(), vec2.begin(),vec2.end(),result.begin(), comp);
	result.erase(iter, result.end());
	return result;
}

vector<Record> RecordManager::common_records(vector<Record> vec1, vector<Record> vec2)
{
	vector<Record> result(vec1.size());
	RecordCompare comp;
	vector<Record>::iterator iter = set_intersection(vec1.begin(), vec1.end(), vec2.begin(),vec2.end(),result.begin(), comp);
	result.erase(iter, result.end());
	return result;
}
